package dao.base;

import anno.MyField;
import anno.MyTable;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import utils.JDBCUtil;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.List;

public class BaseDao<T> {

    private JdbcTemplate jdbcTemplate;
    private Class<T> tClass;
    private String tableName;
    private String keyName;
    public BaseDao(Class<T> tClass) {
        this.tClass = tClass;
        //获取注解中的表名
        MyTable myTable = tClass.getDeclaredAnnotation(MyTable.class);
        //判断表是否存在
        if(null != myTable){
            tableName = myTable.value();
            keyName = myTable.keyName();
        }
        jdbcTemplate = new JdbcTemplate(JDBCUtil.getDataSource());
    }

    protected JdbcTemplate getJdbcTemplate(){
        return jdbcTemplate;
    }

    /**
     * 根据id查找
     * @return
     */
    public T findById(Object id){
        try {
            T t = jdbcTemplate.queryForObject("select * from " + tableName + " where " + keyName + " = ?",
                    new BeanPropertyRowMapper<>(tClass), id);
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询所有
     * @return
     */
    public List<T> findAll(){
        try {
            List<T> list = jdbcTemplate.query("select * from " + tableName, new BeanPropertyRowMapper<>(tClass));
            return list;
        } catch (Exception e) {
            return null;
        }
    }


    public int save(T obj){
        try {
            Class<?> objClass = obj.getClass();
            StringBuilder sql = new StringBuilder("insert into ").append(tableName).append("(");
            //获得所有属性
            Field[] fields = tClass.getDeclaredFields();
            for(int i = 0; i < fields.length; i++){
                Field field = fields[i];
                MyField myField = field.getAnnotation(MyField.class);
                //获得对象属性名
                String columnName = field.getName();
                //带有MyField注解的字段表明表中字段名称和对象属性名称不一致，需要用注解的值替换
                if(myField != null){
                    columnName = myField.value();
                }
                //判断是否最后一个字段
                if(i != fields.length - 1){
                    sql.append("`").append(columnName).append("`").append(",");
                }else {
                    sql.append("`").append(columnName).append("`) ").append("values(");
                }
            }
            //最后拼接为sql语句
            for(int i = 0; i < fields.length; i++){
                if(i != fields.length - 1){
                    sql.append("?,");
                }else{
                    sql.append("?)");
                }
            }
            Object[] objects = new Object[fields.length];
            //得到所有obj类(传进来的对象)的属性值
            for(int i = 0; i < fields.length; i++){
                Field field = fields[i];
                //拼接成get方法字符串
                String methodName = "get" +
                        field.getName().substring(0,1).toUpperCase() + field.getName().substring(1);
                //反射获得方法
                Method method = objClass.getDeclaredMethod(methodName);
                //代理执行
                Object o = method.invoke(obj);
                //获得对象
                objects[i] = o;
            }
            int result = jdbcTemplate.update(sql.toString(),objects);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }

    public int update(T obj){
        int result;
        try {
            StringBuilder sb = new StringBuilder();
            sb.append(" update ").append(tableName).append(" set ");
            Class<?> objClass = obj.getClass();
            Field[] fields = objClass.getDeclaredFields();
            int count = 0;
            for (Field field : fields) {
                String fieldName = field.getName();
                String colName = field.getName();
                MyField myField = field.getDeclaredAnnotation(MyField.class);
                if (null != myField) {
                    colName = myField.value();
                }

                String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                Method method = objClass.getDeclaredMethod(methodName);
                Object value = method.invoke(obj);
                if (null != value) {
                    sb.append("`").append(colName).append("`").append(" = ?, ");
                    count++;
                }
            }
            sb.delete(sb.lastIndexOf(","), sb.length());
            sb.append(" where ").append(keyName).append(" = ? ");

            Object[] objects = new Object[count + 1];
            Object id = null;
            int index = 0;
            for (Field field : fields) {
                String fieldName = field.getName();
                String colName = field.getName();
                MyField myField = field.getDeclaredAnnotation(MyField.class);
                if (null != myField) {
                    colName = myField.value();
                }
                String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                Method method = objClass.getDeclaredMethod(methodName);
                Object value = method.invoke(obj);
                if (null != value) {
                    objects[index] = value;
                    index++;
                }

                if (colName.equals(keyName)) {
                    id = value;
                }

            }
            objects[count] = id;
            result = jdbcTemplate.update(sb.toString(), objects);
        } catch (Exception e) {
            return 0;
        }
        return result;
    }


}
